import { Injectable } from '@nestjs/common';
import IResponse from '@/services/response.service';
import IHelper from '@/services/helper.service';
import * as crypto from 'crypto';
import * as path from 'path';
import * as fs from 'fs-extra';
import IConstants from '@/core/constants';
import * as forge from 'node-forge';

@Injectable()
export class JetbrainsService {
  getSign() {
    return IResponse.success({
      // hash: IHelper.hash(32),
      x: this.getX(),
      y: this.getY(),
      z: this.getZ(),
      r: this.getR(),
    });
  }

  getCertificateDir(filename: string, ensure?: false): string {
    const dir: string = path.join(IConstants.publicDir, 'certs');
    const finalPath = path.join(dir, filename);
    if (ensure !== false) {
      fs.ensureFileSync(finalPath);
    }
    return finalPath;
  }

  genCertificate(): void {
    if (fs.existsSync(this.getCertificateDir('ca.key', false))) return;
    const now = Date.now();
    const yesterday = new Date(now - 24 * 60 * 60 * 1000);
    const tenYearsLater = new Date(now + 10 * 365 * 24 * 60 * 60 * 1000);
    // Generate RSA key pair
    const keys = forge.pki.rsa.generateKeyPair({ bits: 4096 });

    // Create a certificate
    const cert = forge.pki.createCertificate();
    cert.publicKey = keys.publicKey;
    cert.serialNumber = forge.util.bytesToHex(forge.random.getBytesSync(16));
    cert.validity.notBefore = yesterday;
    cert.validity.notAfter = tenYearsLater;
    const attrs = [{ name: 'commonName', value: 'Novice-from-2024-01-19' }];

    cert.setSubject(attrs);
    cert.setIssuer(attrs);

    // Self-sign certificate
    cert.sign(keys.privateKey);

    // Convert keys and certificate to PEM format
    const privateKeyPem = forge.pki.privateKeyToPem(keys.privateKey);
    const certPem = forge.pki.certificateToPem(cert);
    fs.writeFileSync(this.getCertificateDir('ca.key'), privateKeyPem, {
      encoding: 'utf8',
    });
    fs.writeFileSync(this.getCertificateDir('ca.pem'), certPem, {
      encoding: 'utf8',
    });
  }

  getPowerConfig() {}

  getX(): string {
    const certPem = fs.readFileSync(
      '/Users/eros/Downloads/jet/jetbra.pem',
      // this.getCertificateDir('jetbra.pem'),
      'utf8',
    );
    const cert = forge.pki.certificateFromPem(certPem);
    const signature = new forge.jsbn.BigInteger(cert.signature, 16);
    return signature.toString();
  }

  getY(): string {
    return '65535';
  }

  getR() {
    // const certPem = fs.readFileSync(this.getCertificateDir('ca.pem'), 'utf8');
    // const cert = forge.pki.certificateFromPem(certPem);
    // // Extract the signature as a BigInt
    // const signature = new forge.jsbn.BigInteger(cert.signature, 16);
    // const signatureBigInt = BigInt(signature.toString());
    // const x = BigInt(this.getX());
    // // return BigInt(this.getY());
    // const y = BigInt(this.getY());
    // const z = BigInt(this.getZ());
    const x = BigInt(
      '399522092185296408243054990030545551268949554025026088435258649036757908902298427527081287250076253572427788964306703074545395786676161858835519350726901877503224646101314788754714264035046582733572866390672830489760048363493943673497904929093498453797029553681163887050599044638505831946414889534435274806681792099606592321762947460605226730753486575696434171634240490135557902088400096663371149427127062203375867394354195304774964900058904240712566430830659966951786155212399530834926056893056126567324957943374189183129052869054226266096297686840713850967989620202280826570096155323602451260184669278812581074291591370895720222452751346323458573246485602294677564150208154942248536582305934600901595693637739004164003419889819785273141096877879733194201388711256661795850987589758995885112264468584537221920140253169442674138244032371743714461670215165964733850441674318567760673391466398443899694957027439198510250579051842546793698049535168010475552010844289145044125713439256003165866935219935238114436465639713615055123439107080112075167166375906375390181492434315016735498877708984734507124942821053696829135048359443441964835757957678703111910228375620296505808260287840047846508493609220920868432800421895367165151271428170',
    );
    const y = BigInt('65537');
    const z = BigInt(
      '860106576952879101192782278876319243486072481962999610484027161162448933268423045647258145695082284265933019120714643752088997312766689988016808929265129401027490891810902278465065056686129972085119605237470899952751915070244375173428976413406363879128531449407795115913715863867259163957682164040613505040314747660800424242248055421184038777878268502955477482203711835548014501087778959157112423823275878824729132393281517778742463067583320091009916141454657614089600126948087954465055321987012989937065785013284988096504657892738536613208311013047138019418152103262155848541574327484510025594166239784429845180875774012229784878903603491426732347994359380330103328705981064044872334790365894924494923595382470094461546336020961505275530597716457288511366082299255537762891238136381924520749228412559219346777184174219999640906007205260040707839706131662149325151230558316068068139406816080119906833578907759960298749494098180107991752250725928647349597506532778539709852254478061194098069801549845163358315116260915270480057699929968468068015735162890213859113563672040630687357054902747438421559817252127187138838514773245413540030800888215961904267348727206110582505606182944023582459006406137831940959195566364811905585377246353'
    );

    return (x ** y % z).toString();
  }

  getZ() {
    const rootCertificate = forge.pki.certificateFromPem(
      fs.readFileSync(this.getCertificateDir('root.pem'), 'utf8'),
    );
    const publicKey = rootCertificate.publicKey;
    // @ts-expect-error: method not in module...
    return publicKey.n.toString(10);
    // forge.jsbn.modpow
  }
}
